/*
 * GMMClusterMapper.h
 *
 *  Created on: 2011-9-27
 *      Author: yong
 */

#ifndef GMMCLUSTERMAPPER_H_
#define GMMCLUSTERMAPPER_H_
/*
 * GMMClusterMapper.h
 *
 *  Created on: Aug 3, 2011
 *      Author: yong
 */

#include<iostream>
#include "Typedef.h"
#include "Page.h"
#include "Config.h"
#include "math/MultiGaussian.h"

namespace distrim
{

template<typename K, typename V1, typename V2>
class GMMClusterMapper: public Mapper<K, V1,
		std::vector<boost::numeric::ublas::matrix<V2> > >
{
private:
	typedef boost::numeric::ublas::matrix<V2> Matrix;
	typedef std::vector<Matrix> MV;
	typedef std::vector<MultiGuassian<V2> > MGV;
	typedef std::vector<V2> WV;
public:
	GMMClusterMapper(KeyValuePage<K, V1, MV> *ptrKeyValuePage
			, const Config &config,
			MV *ptrParam) :
			Mapper<K, V1, MV>(ptrKeyValuePage, config, ptrParam), m_clusterNum(
					config.GetClusterNum()), m_valueElemCount(
					config.GetValueElemCount()), m_vecCalculator(
					m_clusterNum + 1, MultiGuassian<V2>(m_valueElemCount)), m_tV(
					1, m_valueElemCount), m_ptrParam(ptrParam), m_vecCounter(
					m_clusterNum + 1, 0)
	{
	}
	virtual ~GMMClusterMapper()
	{
	}
	virtual void Map(const KeyValue<K, V1> &keyValue)
	{
		// Get point vector as matrix.
		Util::KeyValueToMatrix(keyValue, m_tV);
		size_t maxClusterID = 0;
		double maxProb = 0;
		V2 prob = V2();
		for (size_t c = 1; c < m_clusterNum + 1; ++c)
		{
			prob = m_vecCalculator[c].GetProbability(m_tV);
			if (prob > maxProb)
			{
				maxClusterID = c;
				maxProb = prob;
			}
		}
		m_vecCounter[maxClusterID] += 1;
	}

	inline const std::vector<size_t> &GetCounters() const
	{
		return m_vecCounter;
	}

	inline void Clear()
	{
		std::fill(m_vecCounter.begin(), m_vecCounter.end(), 0);
	}

	inline void SetCalculators(const MV &paramVec)
	{
		BOOST_ASSERT(paramVec.size() == 3 * m_clusterNum + 1);
		for (size_t c = 1; c < m_clusterNum + 1; ++c)
		{
			m_vecCalculator[c].SetMeanSigma(paramVec[c + m_clusterNum],
					paramVec[c + 2 * m_clusterNum]);
		}
	}
private:
	size_t m_clusterNum;
	size_t m_valueElemCount;
	MGV m_vecCalculator;
	Matrix m_tV;
	MV *m_ptrParam;
	std::vector<size_t> m_vecCounter;
};

}

#endif /* GMMCLUSTERMAPPER_H_ */
